package com.even.camerarecoder

import com.even.camerarecoder.aac.AACEncoder
import com.evendai.loglibrary.Timber
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit

class H264ToMp4SaverThread : Thread(TAG) {
    private lateinit var mBlockingQueue: BlockingQueue<MuxerData>
    private lateinit var mH264ToMp4Saver: H264ToMp4Saver
    private var frameLossCount: Int = 0
    private var needRun = true

    init {
        if (recordVideoSwitch) {
            /* 理论上来说这里是会有问题的，如果队列消费的慢，生产的快，则可能产生的问题：
             * 1、因为队列中的数据是复用数据，当队列满时，则新生产的数据将覆盖早期的数据
             * 2、假如h264缓存为3，aac缓存为3,我们希望队列是各放3个对应的数据，但是有可
             *    能其中一种数据放的超过3个，因为队列中是可以放入重复对象的
             * 实际上这些问题不会发生，因为不论是h264数据或是aac数据，只要你放到队列中，
             * 瞬间就会被消费掉，因为MediaMuxer处理数据非常快，每个数据处理仅需0.1毫秒 ~ 1毫秒
             */
            mBlockingQueue = LinkedBlockingQueue(H264Encoder.cacheSize + AACEncoder.cacheSize)
            mH264ToMp4Saver = H264ToMp4Saver()
        }
    }

    fun addH264Data(muxerData: MuxerData) {
        if (recordVideoSwitch && needRun) {
            // codecData是复用对象，当消费数据没有生产数据快时，则旧的codecData就有风险被新的codecData覆盖。
            val offer = mBlockingQueue.offer(muxerData)
            if (!offer) {
                Timber.i("保存H264为Mp4文件时丢帧：${++frameLossCount}帧")
            }
        }
    }

    override fun run() {
        if (!recordVideoSwitch) return
        try {
            while (needRun) {
                mBlockingQueue.poll(30L, TimeUnit.MILLISECONDS)?.let {
                    if (needRun) {
                        mH264ToMp4Saver.h264ToMp4(it)
                    }
                }
            }
        } catch (e: Exception) {
            Timber.e(e,"把H264保存为mp4时出现异常")
            mH264ToMp4Saver.checkHasSDCard()
        }
    }

    fun close() {
        instance = null
        needRun = false
        if (recordVideoSwitch) {
            try {
                mH264ToMp4Saver.close()
            } catch (e: Exception) {
                Timber.fe(e,"关闭${H264ToMp4Saver::class.java.simpleName}时出现异常")
            }
        }
    }

    companion object {
        private val TAG = H264ToMp4SaverThread::class.java.simpleName
        /** 控制是否需要录视频的开关，默认为true录视频 */
        var recordVideoSwitch = true
        private var instance: H264ToMp4SaverThread? = null
        fun newInstance() = H264ToMp4SaverThread().also { instance = it }
        fun getInstance() = instance
    }

}
